package com.lock;



import com.control.BatchCompareControl;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class RedisLockUtils {

    private final static Logger logger = LoggerFactory.getLogger(BatchCompareControl.class);


    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * @param lockKey    锁
     * @param value      身份标识（保证锁不会被其他人释放）
     * @param expireTime 锁的过期时间（单位：秒）
     * @return 成功返回true, 失败返回false
     */
    public boolean lock(String lockKey, String value, long expireTime) {
        return stringRedisTemplate.opsForValue().setIfAbsent(lockKey, value, expireTime, TimeUnit.SECONDS);
    }

    /**
     * redisTemplate解锁
     * @param key
     * @param value
     * @return 成功返回true, 失败返回false
     */
    public boolean unlock(String key, String value) {
        String currentValue = stringRedisTemplate.opsForValue().get(key);
        boolean result = false;
        if (StringUtils.isNoneBlank(currentValue) && currentValue.equals(value)) {
            result = stringRedisTemplate.opsForValue().getOperations().delete(key);
        }
        return result;
    }

    /**
     * redisTemplate解锁
     * @param key
     * @param uuid
     * @return 成功返回true, 失败返回false
     */
    public Long unlockScript(String key, String uuid) {

        String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";

        //使用函数执行删锁脚本
        Long result = stringRedisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(key), uuid);

        return result;
    }

    /**
     * 使用lua脚本更新redis锁的过期时间
     * @param lockKey
     * @param value
     * @return 成功返回true, 失败返回false
     */
    public boolean renewal(String lockKey, String value, int expireTime) {
        String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('expire', KEYS[1], ARGV[2]) else return 0 end";
        DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>();
        redisScript.setResultType(Boolean.class);
        redisScript.setScriptText(luaScript);
        List<String> keys = new ArrayList<>();
        keys.add(lockKey);
        Object result = stringRedisTemplate.execute(redisScript, keys, value, expireTime);
        logger.info("更新redis锁的过期时间：{}", result);
        return (boolean) result;
    }
}